﻿using Microsoft.Win32;
using System;
using System.Configuration;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;

namespace SocketClient
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        ClientMainWindowViewModel clientMainWindowViewModel = new ClientMainWindowViewModel();
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = clientMainWindowViewModel;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            string sendStr = MsgText.Text.ToString();
            ClientMainWindowViewModel.ClientSendMsg(sendStr);
            MsgText.Text = "";
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            txtReceived.ScrollToEnd();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            try
            {
                if (e.Key == Key.Enter)
                {
                    Button_Click(null, null);
                }
            }
            catch (Exception)
            {
            }
        }

        private void Window_Unloaded(object sender, RoutedEventArgs e)
        {
            string sendStr = "下线";
            ClientMainWindowViewModel.ClientSendMsg(sendStr);
        }

        private void Rectangle_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)

                DragMove();
        }

        private void Button_Click_3(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void Button_Click_4(object sender, RoutedEventArgs e)
        {
            this.WindowState = WindowState.Minimized;
        }
        /// <summary>
        /// 浏览文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            //打开文件
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "选择要传的文件";
            ofd.InitialDirectory = @"C:\Users\Administrator\Desktop";
            ofd.Filter = "所有文件|*.*";
            ofd.ShowDialog();
            //得到选择文件的路径
            txtPath.Text = ofd.FileName;
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            SocketClientSendBigFile();
        }
        public static string serverIp = ConfigurationManager.AppSettings["ServiceIp"];//设置服务端IP
        public static int serverPort = Convert.ToInt32(ConfigurationManager.AppSettings["Port"]);//服务端端口
        public static Socket socketClient;//定义socket
        public void SocketClientSendBigFile()
        {
            socketClient = ClientMainWindowViewModel.SocketClient;
            try
            {
                Thread.Sleep(1000);    //等待1秒钟  
                //通过 socketClient 向服务器发送数据
                string sendMessage = "已成功接到SocketClient发送的消息";//发送到服务端的内容
                byte[] send = Encoding.UTF8.GetBytes(sendMessage);//Encoding.UTF8.GetBytes()将要发送的字符串转换成UTF8字节数组
                byte[] SendMsg = new byte[send.Length + 1];//定义新的字节数组
                SendMsg[0] = 0;//将数组第一位设置为0，来表示发送的是消息数据  
                Buffer.BlockCopy(send, 0, SendMsg, 1, send.Length);//偏移复制字节数组
                socketClient.Send(SendMsg);  //将接受成功的消息返回给SocketServer服务器 
                ThreadPool.QueueUserWorkItem(delegate
                {
                    SynchronizationContext.SetSynchronizationContext(new
                    DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
                    SynchronizationContext.Current.Post(pl =>
                    {
                        txtMsgInfo.Text = "发送完毕：" + sendMessage;
                    }, null);
                });
            }
            catch
            {
                socketClient.Shutdown(SocketShutdown.Both);//禁止Socket上的发送和接受
                socketClient.Close();//关闭Socket并释放资源
            }
            //打开文件
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "选择要传的文件";
            ofd.InitialDirectory = @"D:\project";
            //ofd.Filter = "文本文件|*.txt|图片文件|*.jpg|视频文件|*.avi|所有文件|*.*";
            ofd.ShowDialog();
            //得到选择文件的路径
            string filePath = ofd.FileName;//获取文件的完整路径
            ThreadPool.QueueUserWorkItem(delegate
            {
                SynchronizationContext.SetSynchronizationContext(new
                DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
                SynchronizationContext.Current.Post(pl =>
                {
                    txtMsgInfo.Text = "发送的文件路径为：" + filePath;
                }, null);
            });
            Task.Factory.StartNew(() =>
            {
                using (FileStream fsRead = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Read))
                {
                    //1. 第一步：发送一个文件，表示文件名和长度，让客户端知道后续要接收几个包来重新组织成一个文件
                    string fileName = Path.GetFileName(filePath);
                    ThreadPool.QueueUserWorkItem(delegate
                    {
                        SynchronizationContext.SetSynchronizationContext(new
                        DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
                        SynchronizationContext.Current.Post(pl =>
                        {
                            txtMsgInfo.Text = "发送的文件名是：" + fileName;
                        }, null);
                    });
                    long fileLength = fsRead.Length;//文件长度
                    ThreadPool.QueueUserWorkItem(delegate
                    {
                        SynchronizationContext.SetSynchronizationContext(new
                        DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
                        SynchronizationContext.Current.Post(pl =>
                        {
                            txtMsgInfo.Text = "发送的文件长度为：" + fileLength;
                        }, null);
                    });
                    string totalMsg = string.Format("{0}-{1}", fileName, fileLength);
                    byte[] buffer = Encoding.UTF8.GetBytes(totalMsg);
                    byte[] newBuffer = new byte[buffer.Length + 1];
                    newBuffer[0] = 2;
                    Buffer.BlockCopy(buffer, 0, newBuffer, 1, buffer.Length);
                    socketClient.Send(newBuffer);//发送文件前，将文件名和长度发过去
                                                 //2第二步：每次发送一个1MB的包，如果文件较大，则会拆分为多个包
                    byte[] Filebuffer = new byte[1024 * 1024 * 5];//定义1MB的缓存空间
                    int readLength = 0;  //定义读取的长度
                    bool firstRead = true;
                    long sentFileLength = 0;//定义发送的长度
                    while ((readLength = fsRead.Read(buffer, 0, buffer.Length)) > 0 && sentFileLength < fileLength)
                    {
                        sentFileLength += readLength;
                        //第一次发送的字节流上加个前缀1
                        if (firstRead)
                        {
                            byte[] firstBuffer = new byte[readLength + 1];
                            firstBuffer[0] = 1;//标记1，代表为文件
                            Buffer.BlockCopy(buffer, 0, firstBuffer, 1, readLength);
                            socketClient.Send(firstBuffer, 0, readLength + 1, SocketFlags.None);
                            //ThreadPool.QueueUserWorkItem(delegate
                            //{
                            //    SynchronizationContext.SetSynchronizationContext(new
                            //    DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
                            //    SynchronizationContext.Current.Post(pl =>
                            //    {
                            //        txtMsgInfo.Text = "第一次读取数据成功，在前面添加一个标记";
                            //    }, null);
                            //});
                            firstRead = false;
                            continue;
                        }
                        socketClient.Send(buffer, 0, readLength, SocketFlags.None);
                        Task.Factory.StartNew(() => NewMethod(fileLength, sentFileLength));

                    }
                    fsRead.Close();
                    ThreadPool.QueueUserWorkItem(delegate
                    {
                        SynchronizationContext.SetSynchronizationContext(new
                        DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
                        SynchronizationContext.Current.Post(pl =>
                        {
                            txtMsgInfo.Text = "发送完成";
                        }, null);
                    });

                }
            });
        }

        private void NewMethod(long fileLength, long sentFileLength)
        {
            ThreadPool.QueueUserWorkItem(delegate
            {
                SynchronizationContext.SetSynchronizationContext(new
                DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher));
                SynchronizationContext.Current.Post(pl =>
                {
                    this.Lith.Value = Convert.ToDouble(sentFileLength) / Convert.ToDouble(fileLength) * 100;
                    txtMsgInfo.Text = string.Format("{0}: 已发送数据：{1}/{2}", socketClient.RemoteEndPoint, sentFileLength, fileLength);
                }, null);
            });
        }
    }
}
